<?php

namespace App\Http\Controllers\QH_Api;

use App\Events\UserLearnLimitCheckEvent;
use App\Http\Controllers\TK_Api\ApiBaseController;
use App\Jobs\UserLearnQuestionHelperJob;
use App\Jobs\UserQuestionLearnLogDeleteJob;
use App\Jobs\UserQuestionLearnLogToDbJob;
use App\Models\Qh_KaoshiResult;
use App\Models\Qh_Knowledge;
use App\Models\Qh_LitQuestion;
use App\Models\Qh_Question;
use App\Models\Qh_Rank;
use App\Models\Qh_UserCollectQuestion;
use App\Models\User;
use App\Service\Redis\RedisBaseService;
use Auth;
use Carbon\Carbon;
use DB;
use Exception;
use Illuminate\Http\JsonResponse;
use Log;
use Throwable;
use Validator;

class QuestionController extends ApiBaseController
{

    /**
     * 获取知识点下试题的初始化数据
     * @return JsonResponse|object
     * @throws Exception
     */
    public function getQuestionsByKnowledge()
    {
        if ($this->user && $this->user->status == 'ban') {
            return $this->restful(null, false, '防盗刷机制，请联系客服！');
        }

        $knowledgeIds = explode(',', request('ids', null));
        if (count($knowledgeIds) < 1) throw new Exception('该知识点无题');

        $questions = Qh_Question::selectRaw('id')
            ->whereIn('knowledgeId', $knowledgeIds)
            ->get();
        // 统计数量
        $data = [
            'questionCount' => count($questions),
            'userRightCount' => 0,
            'userWrongCount' => 0,
            'list' => $questions
        ];

        return $this->restful($data);
    }

    /**
     * 获取知识点下的试题初始化数据
     * @return JsonResponse|object
     * @throws Exception
     */
    public function getQuestionsResultByKnowledge() {
        if ($this->user && $this->user->status == 'ban') {
            return $this->restful(null, false, '防盗刷机制，请联系客服！');
        }

        $knowledgeIds = explode(',', request('ids', null));
        if (count($knowledgeIds) < 1) throw new Exception('该知识点无题');

        if (is_null($this->user)) return $this->restful();

        $results = DB::table('qh_user_question_logs')
            ->selectRaw('questionId as id, result, userAnswer')
            ->where('userId', $this->user->id)
            ->whereIn('knowledgeId', $knowledgeIds)
            ->get();

        return $this->restful($results);
    }

    /**
     * 根据错题集获取试题的初始化数据
     * @return JsonResponse|object
     */
    public function getQuestionsByCuoti()
    {
        $qIds = DB::table('qh_user_question_logs')->where('userId', $this->user->id)->where('result', 2)->pluck('questionId')->toArray();

        $data = $this->getQuestionInitData($qIds);
        return $this->restful($data);
    }

    public function getQuestionsByWrongOrCollect(RedisBaseService $redisBaseService) {
        $params = request()->validate([
            'knowledgeId' => 'bail|required|numeric',
            'type' => 'bail|required|numeric|in:1,2'
        ], request()->all());

        $userWrongQuestionStructureData = $redisBaseService->getUserWrongOrCollectQuestionStructureData($this->user->id, $params['type']);

        $qIds = getLevelDataFromWrongOrCollectQuestionStructureData($userWrongQuestionStructureData, 3, $params['knowledgeId']);

        $data = $this->getQuestionInitData($qIds);
        return $this->restful($data);
    }

    /**
     * 根据用户的收藏获取试题的初始化数据
     * @return JsonResponse|object
     */
    public function getQuestionsByCollect()
    {
        $qIds = Qh_UserCollectQuestion::where('userId', $this->user->id)->pluck('questionId')->toArray();
        $data = $this->getQuestionInitData($qIds);
        return $this->restful($data);
    }

    private function getQuestionInitData($ids)
    {
        $questions = Qh_Question::selectRaw('id')
            ->whereIn('id', $ids)
            ->get();

        // 统计数量
        $data = [
            'questionCount' => count($questions),
            'userRightCount' => 0,
            'userWrongCount' => 0,
            'list' => $questions
        ];

        if (Auth::guard('api')->check()) {
            $user = Auth::guard('api')->user();
            foreach ($questions as $question) {
                $result = DB::table('qh_user_question_logs')->where('userId', $user->id)->where('questionId', $question->id)->value('result');
                if (!is_null($result)) {
                    if ($result == 1) $data['userRightCount'] += 1;
                    else $data['userWrongCount'] += 1;
                }
            }
        }
        return $data;
    }

    /**
     * 根据ids获取试题
     * @return JsonResponse|object
     */
    public function getQuestionsByIds()
    {
        $ids = explode(',', request('ids'));
        $ids = array_unique($ids);

        $questions = Qh_Question::selectRaw('*')
            ->whereIn('id', $ids)
            ->with(['children' => function ($c) {
                $c->selectRaw('*');
            }])
            ->get();

        // 增加坚持天数
        if (Auth::guard('api')->check()) {
            if (is_null($this->user->lastKsDay) || !Carbon::make($this->user->lastKsDay)->isToday()) {
                $this->user->ksDaysCount += 1;
                $this->user->lastKsDay = Carbon::now();
                $this->user->save();
            }
        }

        return $this->restful($questions);
    }

    /**
     * 答题结果汇报
     * @return JsonResponse|object
     * @throws Throwable
     */
    public function answerResultCheck(RedisBaseService $redisBaseService)
    {
        $params = request()->validate([
            'questionIds' => 'bail|required|numeric',
            'result' => 'bail|required|numeric|in:1,2',
            'answer' => 'bail|nullable',
            'type' => 'bail|nullable|string'
        ], request()->all());

        $question = Qh_Question::findOrFail($params['questionIds']);
        if ($question) {
            try {
                /**
                 * 更新答题数据
                 */
                $allCount = $redisBaseService->getUserStatisticsData('statistics:userLearnQuestionCount', $this->user->id);
                $todayCount = $redisBaseService->getUserStatisticsData('statistics:userLearnQuestionOfTodayCount', $this->user->id);
                $todayTimestamp = $redisBaseService->getUserStatisticsData('statistics:userTodayTimestamp', $this->user->id);
                // 记录刷题记录到缓存
                if ($todayTimestamp == null || !Carbon::createFromTimestamp($todayTimestamp)->isToday()) {
                    $todayCount = 0;
                }
                $redisBaseService->updateUserLearnQuestionCount($this->user->id, $allCount + 1, $todayCount + 1);

                // 更新学科、章、节的数量
                $redisBaseService->updateUserLearnQuestionCountByCourse($this->user->id, $question->courseId, $redisBaseService->getUserLearnQuestionCountByCourse($this->user->id, $question->courseId)+1);

                $knowledge2 = DB::table('qh_knowledge')->select(['id', 'parentId'])->where('id', $question->knowledgeId)->first();

                if ($knowledge2) {
                    $redisBaseService->updateUserLearnQuestionCountByKnowledge($this->user->id, $knowledge2->id, $redisBaseService->getUserLearnQuestionCountByKnowledge($this->user->id, $knowledge2->id)+1);
                    $redisBaseService->updateUserLearnQuestionCountByKnowledge($this->user->id, $knowledge2->parentId, $redisBaseService->getUserLearnQuestionCountByKnowledge($this->user->id, $knowledge2->parentId)+1);
                }

                /**
                 * 保存答题记录到缓存
                 */
                $redisBaseService->updateUserLearnQuestionLog($this->user->id, $question, $params);
                // 创建记录答题记录入库任务
                UserQuestionLearnLogToDbJob::dispatch($this->user->id, $question, $params, 1);
            }catch (Exception $e) {
                return $this->restful(null, false, '系统维护中');
            }
        }

        return $this->restful();
    }

    /**
     * 考试模式答题记录
     * @return JsonResponse|object
     * @throws Throwable
     */
    public function answerResultCheckOfKaoshi(RedisBaseService $redisBaseService)
    {
        $params = request()->validate([
            'questionIds' => 'bail|required|numeric',
            'result' => 'bail|required|numeric|in:1,2',
            'answer' => 'bail|nullable'
        ], request()->all());

        $question = Qh_Question::findOrFail($params['questionIds']);
        if ($question) {
            try {
                // 记录答题记录到缓存
                $redisBaseService->updateUserLearnQuestionLog($this->user->id, $question, $params, 3);
                // 创建记录答题记录入库任务
                UserQuestionLearnLogToDbJob::dispatch($this->user->id, $question, $params, 3);
            }catch (Exception $e) {
                return $this->restful(null, false, '系统维护中');
            }
        }

        return $this->restful();
    }

    /**
     * 小题答题结果汇报
     * @return JsonResponse|object
     * @throws Throwable
     */
    public function answerResultCheckOfLit()
    {
        $params = request()->validate([
            'questionIds' => 'bail|required|numeric',
            'result' => 'bail|required|numeric|in:1,2',
            'answer' => 'bail|nullable'
        ], request()->all());


        $question = Qh_LitQuestion::findOrFail($params['questionIds']);
        if (empty($question->knowledgeId)) {
            $parentQuestion = Qh_Question::find($question->parentId);
            if ($parentQuestion) {
                $question->qlId = $parentQuestion->qlId;
                $question->courseId = $parentQuestion->courseId;
                $question->knowledgeId = $parentQuestion->knowledgeId;
                $question->save();
            }
        }
        \Illuminate\Support\Facades\DB::transaction(function () use ($question, $userAnswer) {
            try {
                $questionIdInLogs = intval('999999' . $question->id);
                $log = Db::table('qh_user_question_logs')->where('userId', $this->user->id)->where('questionId', $questionIdInLogs)->first();
                if (!$log) {
                    // 记录
                    DB::table('qh_user_question_logs')->updateOrInsert([
                        'userId' => $this->user->id,
                        'qlId' => $question->qlId,
                        'courseId' => $question->courseId,
                        'knowledgeId' => $question->knowledgeId,
                        'questionId' => $questionIdInLogs,
                        'result' => $this->params['result'],
                        'userAnswer' => $userAnswer,
                        'created_at' => Carbon::now()
                    ]);
                } else {
                    // 更新
                    if ($log->result != $this->params['result'] or $log->userAnswer != $userAnswer) {
                        Db::table('qh_user_question_logs')
                            ->where('id', $log->id)
                            ->update(['result' => $this->params['result'], 'userAnswer' => $userAnswer, 'updated_at' => Carbon::now()]);
                    }
                }

                // 正确
                if ($this->params['result'] == 1) {
                    // 更新正确次数
                    $question->rightCount += 1;
                }

                // 错误
                if ($this->params['result'] == 2) {
                    // 更新错误次数
                    $question->wrongCount += 1;
                }

                $question->save();
            }catch (\Exception $e) {
                return $this->restful(null, false, '系统维护中');
            }
        });

        return $this->restful();
    }

    /**
     * 考试结果汇报
     * @return JsonResponse|object
     */
    public function kaoshiResultCheck()
    {
        $params = Validator::validate(request()->all(), [
            'knowledgeId' => 'bail|required|integer',
            'seconds' => 'bail|required|integer',
            'score' => 'bail|required|integer',
        ]);

        $result = Qh_KaoshiResult::where('userId', $this->user->id)->where('knowledgeId', $params['knowledgeId'])->first();

        if ($result) {
            // 排名用Qh_KaoshiResult，每次重做入值用qh_kaoshi_results_update

            // $resultUpdateId = DB::table('qh_kaoshi_results_update')
            //     ->where('userId', $this->user->id)
            //     ->where('knowledgeId', $params['knowledgeId'])
            //     ->value('id');
            $resultUpdate = DB::table('qh_kaoshi_results_update')
                ->where('userId', $this->user->id)
                ->where('knowledgeId', $params['knowledgeId'])->first();
            if ($resultUpdate) {
                $resultUpdateId = $resultUpdate->id;
                DB::table('qh_kaoshi_results_update')
                    ->where('userId', $this->user->id)
                    ->where('knowledgeId', $params['knowledgeId'])
                    ->update([
                        'seconds' => $params['seconds'],
                        'score' => $params['score'],
                        'updated_at' => Carbon::now(),
                    ]);
            }else {
                $resultUpdateId = DB::table('qh_kaoshi_results_update')->insertGetId([
                    'knowledgeId' => $params['knowledgeId'],
                    'userId' => $this->user->id,
                    'seconds' => $params['seconds'],
                    'score' => $params['score'],
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ]);
            }
        } else {
            $result = Qh_KaoshiResult::create([
                'knowledgeId' => $params['knowledgeId'],
                'userId' => $this->user->id,
                'seconds' => $params['seconds'],
                'score' => $params['score']
            ]);
            $resultUpdateId = DB::table('qh_kaoshi_results_update')->insertGetId([
                'knowledgeId' => $params['knowledgeId'],
                'userId' => $this->user->id,
                'seconds' => $params['seconds'],
                'score' => $params['score'],
                'created_at' => Carbon::now(),
                'updated_at' => Carbon::now(),
            ]);
        }
        $result->resultUpdateId = $resultUpdateId;
        return $this->restful($result);
    }

    /**
     * 重新考试，清空上次的记录
     * @return JsonResponse|object
     */
    public function reKaoshi() {
        $knowledgeId = request('knowledgeId');
        DB::table('qh_user_kaoshi_question_logs')->where('knowledgeId', $knowledgeId)->delete();
        DB::table('qh_user_question_logs')->where('knowledgeId', $knowledgeId)->delete();
        return $this->restful();
    }

    /**
     * 获取考试结果
     * @param $id
     * @return JsonResponse|object
     */
    public function getKaoshiResult($id)
    {
        $result = DB::table('qh_kaoshi_results_update')->where('userId', $this->user->id)->where('id', $id)->first();
        //$result = Qh_KaoshiResult::where('userId', $this->user->id)->where('id', $id)->first();

        if (!$result) return $this->restful();

        $result->questions = Qh_Question::selectRaw('id')
            ->where('knowledgeId', $result->knowledgeId)
            ->get();

        $result->knowledge = Qh_Knowledge::find($result->knowledgeId);

        // 排名
        $result->rank = Qh_KaoshiResult::select(['userId', 'score', 'seconds'])
            // ->addSelect(DB::raw('(SELECT COUNT(*)+1 FROM qh_kaoshi_results AS t2 WHERE knowledgeId=81 AND t2.score > qh_kaoshi_results.score OR (t2.score = qh_kaoshi_results.score AND t2.seconds < qh_kaoshi_results.seconds)) AS rank'))
            ->addSelect(DB::raw("(SELECT COUNT(*)+1 FROM qh_kaoshi_results AS t2 WHERE knowledgeId=$result->knowledgeId AND (t2.score > qh_kaoshi_results.score OR (t2.score = qh_kaoshi_results.score AND t2.seconds < qh_kaoshi_results.seconds))) AS rank"))
            ->where('userId', $this->user->id)
            ->where('knowledgeId', $result->knowledgeId)
            ->first();
        $result->rank = $result->rank ? $result->rank->rank : 0;

        $result->allSeconds = DB::table('qh_kaoshi_results_update')->where('knowledgeId', $result->knowledgeId)->sum('seconds');
        $result->allScore = DB::table('qh_kaoshi_results_update')->where('knowledgeId', $result->knowledgeId)->sum('score');
        $result->count = DB::table('qh_kaoshi_results_update')->where('knowledgeId', $result->knowledgeId)->count();

        $result->allSecondsOfFirst = Qh_KaoshiResult::where('knowledgeId', $result->knowledgeId)->sum('seconds');
        $result->allScoreOfFirst = Qh_KaoshiResult::where('knowledgeId', $result->knowledgeId)->sum('score');
        $result->countOfFirst = Qh_KaoshiResult::where('knowledgeId', $result->knowledgeId)->count();

        // $result->allSeconds = Qh_KaoshiResult::where('knowledgeId', $result->knowledgeId)->sum('seconds');
        // $result->allScore = Qh_KaoshiResult::where('knowledgeId', $result->knowledgeId)->sum('score');
        // $result->count = Qh_KaoshiResult::where('knowledgeId', $result->knowledgeId)->count();

        return $this->restful($result);
    }

    /**
     * 清空小结的答题记录
     * @param $id
     * @param RedisBaseService $redisBaseService
     * @return JsonResponse|object
     * @throws Throwable
     */
    public function clearQuestionLogByKnowledge($id, RedisBaseService $redisBaseService)
    {
        DB::transaction(function () use ($id, $redisBaseService) {
            try {
                $questionIds = DB::table('qh_questions')->where('knowledgeId', $id)->pluck('id')->toArray();

                // 先清空缓存中的
                $redisBaseService->deleteUserLearnQuestionLogMany($this->user->id, $questionIds);

                // 删除数据库中的数据-队列
                UserQuestionLearnLogDeleteJob::dispatchSync($this->user->id, $questionIds);
            } catch (Exception $e) {
                throw new Exception('暂不支持重置');
            }
        });

        return $this->restful();
    }

    /**
     * 清空指定ID的答题记录
     * @return JsonResponse|object
     * @throws Throwable
     */
    public function clearQuestionLogByIds() {
        $questionIds = request('ids', []);

        DB::transaction(function () use ($questionIds) {
            try {
                $knowledgeIds = Qh_Question::whereIn("id", $questionIds)->pluck('knowledgeId')->toArray();
                $knowledgeIds = array_unique($knowledgeIds);

                // 获取答题日志
                $logs = Db::table('qh_user_question_logs')->where('userId', $this->user->id)->whereIn('questionId', $questionIds)->get();
                foreach ($logs as $log) {
                    $question = Qh_Question::find($log->questionId);
                    if (!$question) continue;

                    // 更新正确次数
                    if ($log->result == 1) $question->rightCount -= 1;
                    // 更新错误次数
                    if ($log->result == 2) $question->wrongCount -= 1;

                    $question->save();
                }
                // 清空学习记录
                DB::table('qh_user_learn')->where('userId', $this->user->id)->whereIn('knowledgeId', $knowledgeIds)->delete();
                // 删除答题日志
                Db::table('qh_user_question_logs')->where('userId', $this->user->id)->whereIn('questionId', $questionIds)->delete();

                // 删除刷题记录
                DB::table('qh_user_learn_question_logs')->where('userId', $this->user->id)->whereIn('questionId', $questionIds)->delete();
            } catch (Exception $e) {
                Log::error($e);
                throw new Exception('暂不支持重置');
            }
        });

        return $this->restful();
    }

    /**
     * 收藏
     * @return JsonResponse|object
     * @throws Exception
     */
    public function collect()
    {
        $id = request('id');
        if (empty($id)) throw new Exception('收藏失败');
        $question = Qh_Question::find($id);
        if ($question) {
            $collect = Qh_UserCollectQuestion::where('userId', $this->user->id)->where('questionId', $id)->first();
            if ($collect) {
                // 收藏出库
                (new RedisBaseService())->popWrongOrCollectQuestion($this->user->id, $question, 2);

                $collect->delete();
            }else {
                Qh_UserCollectQuestion::create([
                    'userId' => $this->user->id,
                    'qlId' => $question->qlId,
                    'courseId' => $question->courseId,
                    'knowledgeId' => $question->knowledgeId,
                    'questionId' => $id,
                ]);

                // 收藏入库
                (new RedisBaseService())->pushWrongOrCollectQuestionToDb($this->user->id, $question, 2);
            }
        }
        return $this->restful();
    }

    /**
     * 刷题记录
     * @param RedisBaseService $redisBaseService
     * @return JsonResponse|object
     * @throws \RedisException
     */
    public function learn(RedisBaseService $redisBaseService)
    {
        $questionId = request('id');
        if (!empty($questionId) && Auth::guard('api')->check()) {
            $question = DB::table('qh_questions')->find($questionId);
            if ($question) {
                //$allCount = $redisBaseService->getUserStatisticsData('statistics:userLearnQuestionCount', $this->user->id);
                //$todayCount = $redisBaseService->getUserStatisticsData('statistics:userLearnQuestionOfTodayCount', $this->user->id);
                //$todayTimestamp = $redisBaseService->getUserStatisticsData('statistics:userTodayTimestamp', $this->user->id);
                //// 记录刷题记录到缓存
                //if ($todayTimestamp == null || !Carbon::createFromTimestamp($todayTimestamp)->isToday()) {
                //    $todayCount = 0;
                //}
                //$redisBaseService->updateUserLearnQuestionCount($this->user->id, $allCount + 1, $todayCount + 1);
                //
                //// 更新学科、章、节的数量
                //$redisBaseService->updateUserLearnQuestionCountByCourse($this->user->id, $question->courseId, $redisBaseService->getUserLearnQuestionCountByCourse($this->user->id, $question->courseId)+1);
                //
                //$knowledge2 = DB::table('qh_knowledge')->select(['id', 'parentId'])->where('id', $question->knowledgeId)->first();
                //
                //if ($knowledge2) {
                //    $redisBaseService->updateUserLearnQuestionCountByKnowledge($this->user->id, $knowledge2->id, $redisBaseService->getUserLearnQuestionCountByKnowledge($this->user->id, $knowledge2->id)+1);
                //    $redisBaseService->updateUserLearnQuestionCountByKnowledge($this->user->id, $knowledge2->parentId, $redisBaseService->getUserLearnQuestionCountByKnowledge($this->user->id, $knowledge2->parentId)+1);
                //}

                // 创建刷题记录入库任务
                UserLearnQuestionHelperJob::dispatch($questionId, $this->user, []);
            }

            // 限制检测
            UserLearnLimitCheckEvent::dispatch($this->user->id, 2);
        }

        return $this->restful();
    }
}
